package pagerank;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

//http://mathscinotes.wordpress.com/2012/01/02/worked-pagerank-example/
public class Main {

	private static final double AVG_DIFF_CUTOFF = 0.0001;
	public static final double D = 0.85; // dampingFactor

	public static void main(String args[]) {
		long start = System.currentTimeMillis();
		Parser parser = new Parser();
		// Parse pages and their forwardlinks
		ArrayList<Page> pages = new ArrayList<Page>();
		HashMap<String, Page> pagesMap = parser.parse("linkCollection.xml");
		// add backlinks
		Iterator<Entry<String, Page>> it = pagesMap.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry<String, Page> entry = it.next();
			Page currPage = entry.getValue();
			// System.out.println(currPage.id);
			for (String s : currPage.fLinks) {
				if (pagesMap.containsKey(s)) {
					pagesMap.get(s).bLinks.add(currPage.id);
				} else {// this page links to a non-existing site

				}
			}
		}
		pages.addAll(pagesMap.values());

		// Pages are now in both an ArrayList<Page> and a HashMap<String, Page>,
		// enjoy!

		int nbrOfPages = pages.size();
		// double d = 0.85; // damping factor
		System.out.println("Number of links: " + nbrOfPages);
		// initiate pagerank
		for (Page p : pages) {
			p.oldPageRank = 1 / (double) nbrOfPages;
		}
		for (Page p : pages) {// Get rank from random jump
			p.newPageRank = D + (1 - D) / nbrOfPages;
		}

		PageCollection pageMatrix = new PageCollection(pages, pagesMap);

		double diff = 0;
		int iteration = 0;
		System.out.println("Iteration \tAvg diff");
		do {
			diff = pageMatrix.iteratePagerank();
			iteration++;
			System.out.print(iteration + "\t\t" + diff);
			System.out.println();
		} while (diff > AVG_DIFF_CUTOFF);

		long end = System.currentTimeMillis();
		System.out.println();
		System.out.println("ID \t\t\t\t\tOPR \t\t\tNOPR");
		Collections.sort(pages);
		double oldSum = 0;
		double newSum = 0;
		for (Page page : pages) {
			oldSum += page.oldPageRank;
			newSum += page.newPageRank;
			System.out.println(page.id + "\t" + page.oldPageRank + "\t"
					+ page.newPageRank);
		}
		printToFile(pages);
		System.out.println();
		System.out.println("NewPageRank sum: " + newSum);
		System.out.println("OldPageRank sum: " + oldSum);
		System.out.println();
		System.out.println("Using: " + AVG_DIFF_CUTOFF
				+ " to define convergence,");
		System.out.println("convergance was achieved after " + iteration
				+ " iterations.");
		System.out.println("Execution time: " + (end - start) + " ms");
	}

	public static void printToFile(ArrayList<Page> pages) {
		File f = new File("pagerank.txt");
		try {
			FileWriter fw = new FileWriter(f);
			for (Page p : pages) {
				fw.append(p.id + ";" + p.newPageRank + "\r\n");
			}
			fw.close();

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}